☀️ Analyse de la Production d’Énergie Solaire

Storytelling des données météorologiques et solaires en Tunisie

Author

Projet R - Analyse Solaire

Published

January 7, 2026

🌞 Introduction

Contexte du Projet

Ce rapport présente une analyse complète des données de production d’énergie solaire collectées auprès de différentes stations météorologiques en Tunisie. L’objectif est de comprendre les facteurs qui influencent la production des panneaux solaires et le niveau des batteries.

NoteImportance de l’Analyse

Cette étude permet de :

  • Prévoir l’efficacité des panneaux solaires
  • Optimiser la gestion de l’énergie
  • Identifier les meilleures périodes pour une production maximale
Voir le code
# Chargement des données
df <- read_csv("donnees_cleaned.csv", show_col_types = FALSE)

# Conversion de la date
df <- df %>%
  mutate(
    Date = ymd_hms(Date),
    Year = year(Date),
    Month = month(Date, label = TRUE, abbr = FALSE),
    MonthNum = month(Date),
    Day = day(Date),
    Hour = hour(Date),
    Season = case_when(
      MonthNum %in% c(12, 1, 2) ~ "Hiver",
      MonthNum %in% c(3, 4, 5) ~ "Printemps",
      MonthNum %in% c(6, 7, 8) ~ "Été",
      MonthNum %in% c(9, 10, 11) ~ "Automne"
    ),
    Season = factor(Season, levels = c("Printemps", "Été", "Automne", "Hiver"))
  )

# Aperçu des données
cat("📊 Dimensions du dataset:", nrow(df), "observations,", ncol(df), "variables\n")
📊 Dimensions du dataset: 9324 observations, 20 variables
Voir le code
cat("📍 Stations:", paste(unique(df$nom_station), collapse = ", "), "\n")
📍 Stations: fc, jendouba, mahdia, nabeul 
Voir le code
cat("📅 Période:", as.character(min(df$Date)), "à", as.character(max(df$Date)))
📅 Période: 2024-12-14 11:00:00 à 2025-12-23 23:00:00

Aperçu du Dataset

Voir le code
df %>%
  select(Date, nom_station, Solar.radiation, Solar.Panel, Battery, 
         HC.Air.temperature, HC.Relative.humidity) %>%
  head(100) %>%
  datatable(
    options = list(pageLength = 10, scrollX = TRUE),
    caption = "Aperçu des 100 premières observations",
    filter = "top"
  )

📈 Statistiques Descriptives

Vue d’ensemble des Variables Clés

Voir le code
# Fonction pour calculer les statistiques
calc_stats <- function(x) {
  tibble(
    N = sum(!is.na(x)),
    Moyenne = round(mean(x, na.rm = TRUE), 2),
    Médiane = round(median(x, na.rm = TRUE), 2),
    `Écart-type` = round(sd(x, na.rm = TRUE), 2),
    Variance = round(var(x, na.rm = TRUE), 2),
    Min = round(min(x, na.rm = TRUE), 2),
    Max = round(max(x, na.rm = TRUE), 2),
    `Q1 (25%)` = round(quantile(x, 0.25, na.rm = TRUE), 2),
    `Q3 (75%)` = round(quantile(x, 0.75, na.rm = TRUE), 2)
  )
}

# Statistiques pour les variables principales
stats_table <- bind_rows(
  calc_stats(df$Solar.Panel) %>% mutate(Variable = "Solar Panel", .before = 1),
  calc_stats(df$Solar.radiation) %>% mutate(Variable = "Solar Radiation", .before = 1),
  calc_stats(df$Battery) %>% mutate(Variable = "Battery", .before = 1),
  calc_stats(df$HC.Air.temperature) %>% mutate(Variable = "Température (°C)", .before = 1),
  calc_stats(df$HC.Relative.humidity) %>% mutate(Variable = "Humidité (%)", .before = 1)
)

stats_table %>%
  kable(
    caption = "📊 Statistiques Descriptives des Variables Principales",
    align = "c"
  )
📊 Statistiques Descriptives des Variables Principales
Variable N Moyenne Médiane Écart-type Variance Min Max Q1 (25%) Q3 (75%)
Solar Panel 9324 4475.79 2408.00 4577.72 20955477.68 0.00 10940.00 0.00 9831.25
Solar Radiation 9324 199.64 8.00 284.55 80967.55 0.00 4380.00 0.00 362.00
Battery 9324 6642.82 6562.00 168.22 28298.76 6395.00 6898.00 6484.00 6804.00
Température (°C) 9324 22.19 22.43 6.24 38.92 2.27 46.23 19.49 25.32
Humidité (%) 9324 78.85 83.46 20.07 402.83 8.20 99.99 65.94 99.43
TipObservations Clés
  • La production solaire (Solar Panel) varie considérablement avec une moyenne de 4476 et un maximum de 1.094^{4}
  • La température moyenne est de 22.2°C
  • Le rayonnement solaire moyen atteint 200 W/m²

Distribution des Variables

Production Solaire (Solar Panel)

Voir le code
p1 <- df %>%
  ggplot(aes(x = Solar.Panel)) +
  geom_histogram(aes(y = after_stat(density)), bins = 50, 
                 fill = "#FFD700", color = "white", alpha = 0.8) +
  geom_density(color = "#FF6B35", linewidth = 1.2) +
  geom_vline(aes(xintercept = mean(Solar.Panel, na.rm = TRUE)), 
             color = "#004E89", linetype = "dashed", linewidth = 1) +
  annotate("text", x = mean(df$Solar.Panel, na.rm = TRUE) + 500, 
           y = 0.0002, label = paste("Moyenne:", round(mean(df$Solar.Panel, na.rm = TRUE), 0)),
           color = "#004E89", fontface = "bold") +
  labs(
    title = "Distribution de la Production Solaire",
    subtitle = "Histogramme avec courbe de densité",
    x = "Production (Solar Panel)",
    y = "Densité"
  )

ggplotly(p1)

Distribution de la production des panneaux solaires

Rayonnement Solaire vs Température

Voir le code
p2 <- df %>%
  filter(Solar.radiation > 0) %>%
  ggplot(aes(x = Solar.radiation)) +
  geom_histogram(bins = 40, fill = "#FFA500", color = "white", alpha = 0.8) +
  labs(title = "Distribution du Rayonnement Solaire (> 0)",
       x = "Rayonnement (W/m²)", y = "Fréquence")

p3 <- df %>%
  ggplot(aes(x = HC.Air.temperature)) +
  geom_histogram(bins = 40, fill = "#FF6B35", color = "white", alpha = 0.8) +
  labs(title = "Distribution de la Température",
       x = "Température (°C)", y = "Fréquence")

ggplotly(p2)
ggplotly(p3)

Distributions du rayonnement et de la température

Distributions du rayonnement et de la température

Test de Normalité

Voir le code
# Test de Shapiro-Wilk (échantillon de 5000 max)
set.seed(42)
sample_solar <- sample(df$Solar.Panel, min(5000, nrow(df)))

shapiro_result <- shapiro.test(sample_solar)

cat("🧪 Test de Shapiro-Wilk pour Solar Panel:\n")
🧪 Test de Shapiro-Wilk pour Solar Panel:
Voir le code
cat("   W =", round(shapiro_result$statistic, 4), "\n")
   W = 0.7316 
Voir le code
cat("   p-value =", format.pval(shapiro_result$p.value), "\n")
   p-value = < 2.22e-16 
Voir le code
cat("   Conclusion:", ifelse(shapiro_result$p.value < 0.05, 
                             "❌ Les données ne suivent PAS une distribution normale",
                             "✅ Les données suivent une distribution normale"))
   Conclusion: ❌ Les données ne suivent PAS une distribution normale

🔥 Jours de Production Maximale

Top 10 des Meilleures Journées

Voir le code
top_days <- df %>%
  filter(Solar.Panel > 0) %>%
  group_by(Date = as.Date(Date), nom_station) %>%
  summarise(
    Production_Max = max(Solar.Panel, na.rm = TRUE),
    Rayonnement_Max = max(Solar.radiation, na.rm = TRUE),
    Temp_Moy = round(mean(HC.Air.temperature, na.rm = TRUE), 1),
    Humidite_Moy = round(mean(HC.Relative.humidity, na.rm = TRUE), 1),
    .groups = "drop"
  ) %>%
  arrange(desc(Production_Max)) %>%
  head(10)

top_days %>%
  mutate(Date = as.character(Date)) %>%
  datatable(
    caption = "🏆 Top 10 des Journées avec Production Maximale",
    options = list(pageLength = 10)
  ) %>%
  formatStyle("Production_Max", 
              background = styleColorBar(top_days$Production_Max, "#FFD700"),
              backgroundSize = "98% 88%",
              backgroundRepeat = "no-repeat",
              backgroundPosition = "center")
Important🌟 Insight - Jours de Production Maximale

Les journées les plus productives présentent généralement :

  • Un rayonnement solaire intense (> 900 W/m²)
  • Une température modérée (25-32°C)
  • Une humidité relative basse (< 50%)

La station mahdia a enregistré la production maximale de 10 940 le 2025-09-20.

Évolution Horaire de la Production

Voir le code
hourly_profile <- df %>%
  group_by(Hour) %>%
  summarise(
    Solar_Mean = mean(Solar.Panel, na.rm = TRUE),
    Radiation_Mean = mean(Solar.radiation, na.rm = TRUE),
    Temp_Mean = mean(HC.Air.temperature, na.rm = TRUE),
    .groups = "drop"
  )

p_hourly <- ggplot(hourly_profile, aes(x = Hour)) +
  geom_area(aes(y = Solar_Mean), fill = "#FFD700", alpha = 0.5) +
  geom_line(aes(y = Solar_Mean), color = "#FFA500", linewidth = 1.5) +
  geom_point(aes(y = Solar_Mean), color = "#FF6B35", size = 3) +
  geom_line(aes(y = Radiation_Mean * 10), color = "#004E89", 
            linewidth = 1, linetype = "dashed") +
  scale_y_continuous(
    name = "Production Solaire (Solar Panel)",
    sec.axis = sec_axis(~./10, name = "Rayonnement (W/m²)")
  ) +
  scale_x_continuous(breaks = 0:23) +
  labs(
    title = "Profil Horaire de la Production Solaire",
    subtitle = "Ligne pointillée: Rayonnement solaire",
    x = "Heure de la journée"
  ) +
  theme(axis.title.y.right = element_text(color = "#004E89"))

ggplotly(p_hourly)

Profil horaire moyen de la production solaire


🔗 Analyse des Corrélations

Matrice de Corrélation

Voir le code
# Sélection des variables numériques
cor_vars <- df %>%
  select(Solar.radiation, Solar.Panel, Battery, HC.Air.temperature,
         HC.Relative.humidity, Dew.Point, VPD, DeltaT, 
         U.sonic.wind.speed, Wind.gust, Precipitation) %>%
  drop_na()

# Calcul de la matrice de corrélation
cor_matrix <- cor(cor_vars)

# Visualisation
corrplot(cor_matrix, 
         method = "color",
         type = "upper",
         order = "hclust",
         addCoef.col = "black",
         number.cex = 0.7,
         tl.col = "black",
         tl.srt = 45,
         col = colorRampPalette(c("#004E89", "white", "#FFD700"))(200),
         title = "Matrice de Corrélation - Variables Solaires",
         mar = c(0, 0, 2, 0))

Matrice de corrélation entre les variables clés

Corrélations avec Solar Panel

Voir le code
correlations <- cor_vars %>%
  summarise(across(everything(), ~cor(.x, Solar.Panel, use = "complete.obs"))) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Correlation") %>%
  filter(Variable != "Solar.Panel") %>%
  arrange(desc(abs(Correlation))) %>%
  mutate(
    Direction = ifelse(Correlation > 0, "Positive", "Négative"),
    Correlation = round(Correlation, 3)
  )

p_cor <- ggplot(correlations, aes(x = reorder(Variable, Correlation), 
                                   y = Correlation, fill = Direction)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = Correlation), hjust = ifelse(correlations$Correlation > 0, -0.2, 1.2),
            size = 4) +
  coord_flip() +
  scale_fill_manual(values = c("Positive" = "#FFD700", "Négative" = "#004E89")) +
  labs(
    title = "Corrélations avec la Production Solaire",
    subtitle = "Classement par force de corrélation",
    x = "", y = "Coefficient de corrélation (r)"
  ) +
  theme(legend.position = "top")

ggplotly(p_cor)
Note📊 Interprétation des Corrélations
Relation Corrélation Interprétation
Solar Panel ↔︎ Solar Radiation Très forte Plus le rayonnement est intense, plus la production augmente
Solar Panel ↔︎ Battery Forte La production solaire recharge directement les batteries
Solar Panel ↔︎ VPD Modérée Le déficit de pression de vapeur influence légèrement
Solar Panel ↔︎ Humidité Négative L’humidité réduit l’efficacité des panneaux

Relations Visuelles

Rayonnement Solaire vs Production

Voir le code
p_scatter1 <- df %>%
  filter(Solar.radiation > 0) %>%
  sample_n(min(2000, nrow(.))) %>%
  ggplot(aes(x = Solar.radiation, y = Solar.Panel, color = nom_station)) +
  geom_point(alpha = 0.5, size = 2) +
  geom_smooth(method = "lm", se = TRUE, color = "black", linetype = "dashed") +
  scale_color_manual(values = solar_colors) +
  labs(
    title = "Rayonnement Solaire vs Production",
    subtitle = "Relation linéaire forte attendue",
    x = "Rayonnement Solaire (W/m²)",
    y = "Production (Solar Panel)",
    color = "Station"
  )

ggplotly(p_scatter1)

Relation entre rayonnement solaire et production

Température vs Production

Voir le code
p_scatter2 <- df %>%
  filter(Solar.Panel > 0) %>%
  sample_n(min(2000, nrow(.))) %>%
  ggplot(aes(x = HC.Air.temperature, y = Solar.Panel, color = Solar.radiation)) +
  geom_point(alpha = 0.6, size = 2) +
  scale_color_gradientn(colors = c("#004E89", "#FFD700", "#FF6B35")) +
  geom_smooth(method = "loess", se = TRUE, color = "black") +
  labs(
    title = "Température vs Production Solaire",
    subtitle = "Couleur = Rayonnement solaire",
    x = "Température de l'air (°C)",
    y = "Production (Solar Panel)",
    color = "Rayonnement"
  )

ggplotly(p_scatter2)

Impact de la température sur la production solaire

Warning🌡️ Impact de la Température

Une température trop élevée (> 35°C) peut réduire légèrement le rendement des panneaux solaires. C’est l’effet thermique : les cellules photovoltaïques perdent en efficacité quand elles chauffent trop.

La zone optimale de température pour la production maximale semble être entre 25°C et 32°C.


🗓️ Analyse Saisonnière

Production par Saison

Voir le code
p_season <- df %>%
  filter(Solar.Panel > 0) %>%
  ggplot(aes(x = Season, y = Solar.Panel, fill = Season)) +
  geom_boxplot(alpha = 0.8, outlier.alpha = 0.3) +
  geom_jitter(alpha = 0.1, width = 0.2, size = 0.5) +
  stat_summary(fun = mean, geom = "point", shape = 18, size = 4, color = "black") +
  scale_fill_manual(values = c("Printemps" = "#7CB518", 
                               "Été" = "#FFD700", 
                               "Automne" = "#FF6B35", 
                               "Hiver" = "#004E89")) +
  labs(
    title = "Production Solaire par Saison",
    subtitle = "◆ = Moyenne | Boîte = Médiane et quartiles",
    x = "", y = "Production (Solar Panel)"
  ) +
  theme(legend.position = "none")

ggplotly(p_season)

Distribution de la production solaire par saison

Statistiques par Saison

Voir le code
seasonal_stats <- df %>%
  filter(Solar.Panel > 0) %>%
  group_by(Season) %>%
  summarise(
    N = n(),
    `Moy. Production` = round(mean(Solar.Panel, na.rm = TRUE), 0),
    `Méd. Production` = round(median(Solar.Panel, na.rm = TRUE), 0),
    `Moy. Rayonnement` = round(mean(Solar.radiation, na.rm = TRUE), 0),
    `Moy. Température` = round(mean(HC.Air.temperature, na.rm = TRUE), 1),
    `Moy. Humidité` = round(mean(HC.Relative.humidity, na.rm = TRUE), 1),
    .groups = "drop"
  )

seasonal_stats %>%
  kable(caption = "📅 Statistiques par Saison", align = "c")
📅 Statistiques par Saison
Season N Moy. Production Méd. Production Moy. Rayonnement Moy. Température Moy. Humidité
Été 1544 8503 9746 503 26.9 67.7
Automne 2680 8581 9806 350 24.5 69.9
Hiver 699 8020 9341 203 19.6 81.4

Test de Comparaison Été vs Hiver

Voir le code
# Données été et hiver
ete <- df %>% filter(Season == "Été", Solar.Panel > 0) %>% pull(Solar.Panel)
hiver <- df %>% filter(Season == "Hiver", Solar.Panel > 0) %>% pull(Solar.Panel)

if (length(ete) > 1 & length(hiver) > 1) {
  t_result <- t.test(ete, hiver)
  
  cat("🧪 Test t de Student - Été vs Hiver:\n\n")
  cat("   Moyenne Été:", round(mean(ete), 0), "\n")
  cat("   Moyenne Hiver:", round(mean(hiver), 0), "\n")
  cat("   Différence:", round(mean(ete) - mean(hiver), 0), "\n\n")
  cat("   t =", round(t_result$statistic, 2), "\n")
  cat("   p-value =", format.pval(t_result$p.value), "\n")
  cat("   IC 95%: [", round(t_result$conf.int[1], 0), ",", 
      round(t_result$conf.int[2], 0), "]\n\n")
  cat("   Conclusion:", ifelse(t_result$p.value < 0.05,
                               "✅ Différence SIGNIFICATIVE entre été et hiver",
                               "❌ Pas de différence significative"))
} else {
  cat("⚠️ Données insuffisantes pour le test t")
}
🧪 Test t de Student - Été vs Hiver:

   Moyenne Été: 8503 
   Moyenne Hiver: 8020 
   Différence: 483 

   t = 4.15 
   p-value = 3.4883e-05 
   IC 95%: [ 255 , 711 ]

   Conclusion: ✅ Différence SIGNIFICATIVE entre été et hiver

Évolution Mensuelle

Voir le code
monthly_data <- df %>%
  group_by(MonthNum) %>%
  summarise(
    Solar_Panel = mean(Solar.Panel, na.rm = TRUE),
    Solar_Radiation = mean(Solar.radiation, na.rm = TRUE),
    Temperature = mean(HC.Air.temperature, na.rm = TRUE),
    Humidity = mean(HC.Relative.humidity, na.rm = TRUE),
    Battery = mean(Battery, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(Month = month(MonthNum, label = TRUE, abbr = TRUE))

p_monthly <- ggplot(monthly_data, aes(x = MonthNum)) +
  geom_area(aes(y = Solar_Panel), fill = "#FFD700", alpha = 0.4) +
  geom_line(aes(y = Solar_Panel), color = "#FFA500", linewidth = 1.5) +
  geom_point(aes(y = Solar_Panel), color = "#FF6B35", size = 3) +
  geom_line(aes(y = Solar_Radiation * 10), color = "#004E89", 
            linewidth = 1, linetype = "dashed") +
  geom_line(aes(y = Temperature * 300), color = "#FF0000", 
            linewidth = 1, linetype = "dotted") +
  scale_x_continuous(breaks = 1:12, labels = month.abb) +
  scale_y_continuous(
    name = "Production Solaire",
    sec.axis = sec_axis(~./10, name = "Rayonnement (W/m²)")
  ) +
  labs(
    title = "Évolution Mensuelle - Production, Rayonnement et Température",
    subtitle = "Orange: Production | Bleu pointillé: Rayonnement | Rouge: Température",
    x = "Mois"
  )

ggplotly(p_monthly)

Évolution mensuelle de la production et des conditions météo


📍 Comparaison des Stations

Performance par Station

Voir le code
station_stats <- df %>%
  filter(Solar.Panel > 0) %>%
  group_by(nom_station) %>%
  summarise(
    N = n(),
    Production_Moy = round(mean(Solar.Panel, na.rm = TRUE), 0),
    Production_Max = max(Solar.Panel, na.rm = TRUE),
    Battery_Moy = round(mean(Battery, na.rm = TRUE), 0),
    Rayonnement_Moy = round(mean(Solar.radiation, na.rm = TRUE), 0),
    Temp_Moy = round(mean(HC.Air.temperature, na.rm = TRUE), 1),
    .groups = "drop"
  ) %>%
  arrange(desc(Production_Moy))

p_stations <- station_stats %>%
  ggplot(aes(x = reorder(nom_station, Production_Moy), y = Production_Moy, 
             fill = Production_Moy)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = Production_Moy), hjust = -0.2, fontface = "bold") +
  coord_flip() +
  scale_fill_gradientn(colors = c("#004E89", "#FFD700", "#FF6B35")) +
  labs(
    title = "Production Moyenne par Station",
    subtitle = "Classement des stations les plus productives",
    x = "", y = "Production Moyenne (Solar Panel)"
  ) +
  theme(legend.position = "none")

ggplotly(p_stations)

Comparaison de la production entre stations

Voir le code
station_stats %>%
  datatable(
    caption = "📍 Statistiques Détaillées par Station",
    options = list(pageLength = 10)
  ) %>%
  formatStyle("Production_Moy",
              background = styleColorBar(station_stats$Production_Moy, "#FFD700"))
Tip🏆 Meilleures Stations

La station nabeul est la plus productive avec une moyenne de 8 564.

Ces stations sont idéales pour implanter des installations solaires à grande échelle.


🔋 Analyse des Batteries

Relation Production Solaire → Batterie

Voir le code
p_battery <- df %>%
  sample_n(min(2000, nrow(.))) %>%
  ggplot(aes(x = Solar.Panel, y = Battery, color = HC.Air.temperature)) +
  geom_point(alpha = 0.5, size = 2) +
  geom_smooth(method = "lm", se = TRUE, color = "black") +
  scale_color_gradientn(colors = c("#004E89", "#7CB518", "#FFD700", "#FF6B35")) +
  labs(
    title = "Production Solaire vs Niveau de Batterie",
    subtitle = "Couleur = Température de l'air",
    x = "Production (Solar Panel)",
    y = "Niveau de Batterie",
    color = "Temp (°C)"
  )

ggplotly(p_battery)

Impact de la production solaire sur le niveau de batterie

Distribution du Niveau de Batterie

Voir le code
p_bat_dist <- df %>%
  ggplot(aes(x = Battery)) +
  geom_histogram(bins = 40, fill = "#7CB518", color = "white", alpha = 0.8) +
  geom_vline(aes(xintercept = mean(Battery, na.rm = TRUE)), 
             color = "red", linetype = "dashed", linewidth = 1) +
  labs(
    title = "Distribution des Niveaux de Batterie",
    subtitle = paste("Moyenne:", round(mean(df$Battery, na.rm = TRUE), 0)),
    x = "Niveau de Batterie", y = "Fréquence"
  )

ggplotly(p_bat_dist)

Distribution des niveaux de batterie


📊 Modélisation

Régression Linéaire Simple

Voir le code
# Modèle: Solar Panel ~ Solar Radiation
model_simple <- lm(Solar.Panel ~ Solar.radiation, data = df)

cat("📈 Régression Linéaire Simple: Solar.Panel ~ Solar.radiation\n\n")
📈 Régression Linéaire Simple: Solar.Panel ~ Solar.radiation
Voir le code
summary(model_simple)

Call:
lm(formula = Solar.Panel ~ Solar.radiation, data = df)

Residuals:
   Min     1Q Median     3Q    Max 
-57119  -1962  -1962   2467   7488 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)     1961.7598    36.0411   54.43   <2e-16 ***
Solar.radiation   12.5931     0.1037  121.45   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2849 on 9322 degrees of freedom
Multiple R-squared:  0.6127,    Adjusted R-squared:  0.6127 
F-statistic: 1.475e+04 on 1 and 9322 DF,  p-value: < 2.2e-16

Régression Linéaire Multiple

Voir le code
# Modèle multiple
model_multi <- lm(Solar.Panel ~ Solar.radiation + HC.Air.temperature + 
                    HC.Relative.humidity + VPD + U.sonic.wind.speed, 
                  data = df)

cat("📈 Régression Linéaire Multiple\n\n")
📈 Régression Linéaire Multiple
Voir le code
summary(model_multi)

Call:
lm(formula = Solar.Panel ~ Solar.radiation + HC.Air.temperature + 
    HC.Relative.humidity + VPD + U.sonic.wind.speed, data = df)

Residuals:
   Min     1Q Median     3Q    Max 
-55670  -2123  -1341   2374   8506 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)          4876.8965   315.2716  15.469   <2e-16 ***
Solar.radiation        12.2172     0.1297  94.160   <2e-16 ***
HC.Air.temperature     67.3131     7.3082   9.211   <2e-16 ***
HC.Relative.humidity  -44.4875     3.4217 -13.002   <2e-16 ***
VPD                  -109.2505     9.2705 -11.785   <2e-16 ***
U.sonic.wind.speed     -4.7928     5.6892  -0.842      0.4    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2818 on 9318 degrees of freedom
Multiple R-squared:  0.6213,    Adjusted R-squared:  0.6211 
F-statistic:  3058 on 5 and 9318 DF,  p-value: < 2.2e-16
Voir le code
# Comparaison des modèles
cat("\n📊 Comparaison des Modèles:\n\n")

📊 Comparaison des Modèles:
Voir le code
cat("   R² Simple:", round(summary(model_simple)$r.squared, 4), "\n")
   R² Simple: 0.6127 
Voir le code
cat("   R² Multiple:", round(summary(model_multi)$r.squared, 4), "\n")
   R² Multiple: 0.6213 
Voir le code
cat("   R² Ajusté Multiple:", round(summary(model_multi)$adj.r.squared, 4), "\n")
   R² Ajusté Multiple: 0.6211 

Visualisation du Modèle

Voir le code
df_pred <- df %>%
  drop_na(Solar.radiation, HC.Air.temperature, HC.Relative.humidity, VPD, U.sonic.wind.speed) %>%
  mutate(Predicted = predict(model_multi))

p_pred <- df_pred %>%
  sample_n(min(1000, nrow(.))) %>%
  ggplot(aes(x = Solar.Panel, y = Predicted)) +
  geom_point(alpha = 0.4, color = "#004E89") +
  geom_abline(slope = 1, intercept = 0, color = "#FF6B35", 
              linewidth = 1.5, linetype = "dashed") +
  labs(
    title = "Valeurs Observées vs Prédites",
    subtitle = paste("R² =", round(summary(model_multi)$r.squared, 3)),
    x = "Production Observée", y = "Production Prédite"
  )

ggplotly(p_pred)

Valeurs prédites vs valeurs observées


💡 Conclusions et Insights

Résumé des Découvertes

  • Production maximale : 10 940 enregistrée à la station mahdia
  • Heures optimales : 10h - 14h (pic de rayonnement)
  • Corrélation avec rayonnement : très forte (r > 0.9)
  • Zone optimale : 25°C - 32°C
  • Effet thermique : légère baisse au-delà de 35°C
  • Humidité : effet négatif modéré sur la production
  • Saison la plus productive : Été (juin-août)
  • Différence été/hiver : statistiquement significative
  • Meilleurs mois : juin et juillet
  • Station la plus performante : nabeul
  • Critères d’implantation : rayonnement élevé, humidité basse
  • Potentiel d’optimisation : identifier stations sous-performantes

Recommandations

📋 Actions Recommandées

  1. Optimisation horaire : Concentrer la consommation énergétique entre 10h et 14h
  2. Maintenance préventive : Nettoyer les panneaux en période de forte humidité
  3. Expansion : Prioriser les stations type nabeul pour de nouvelles installations
  4. Stockage : Dimensionner les batteries selon les pics de production
  5. Monitoring : Surveiller l’effet thermique en été

📚 Annexes

Informations de Session

Voir le code
sessionInfo()
R version 4.5.2 (2025-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)

Matrix products: default
  LAPACK version 3.12.1

locale:
[1] LC_COLLATE=French_Tunisia.utf8  LC_CTYPE=French_Tunisia.utf8   
[3] LC_MONETARY=French_Tunisia.utf8 LC_NUMERIC=C                   
[5] LC_TIME=French_Tunisia.utf8    

time zone: Africa/Tunis
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] knitr_1.51      scales_1.4.0    corrplot_0.95   DT_0.34.0      
 [5] plotly_4.11.0   lubridate_1.9.4 forcats_1.0.1   stringr_1.6.0  
 [9] dplyr_1.1.4     purrr_1.2.0     readr_2.1.6     tidyr_1.3.2    
[13] tibble_3.3.0    ggplot2_4.0.1   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       xfun_0.55          bslib_0.9.0        htmlwidgets_1.6.4 
 [5] lattice_0.22-7     tzdb_0.5.0         vctrs_0.6.5        tools_4.5.2       
 [9] crosstalk_1.2.2    generics_0.1.4     parallel_4.5.2     pkgconfig_2.0.3   
[13] Matrix_1.7-4       data.table_1.18.0  RColorBrewer_1.1-3 S7_0.2.1          
[17] lifecycle_1.0.4    compiler_4.5.2     farver_2.1.2       htmltools_0.5.9   
[21] sass_0.4.10        yaml_2.3.12        lazyeval_0.2.2     pillar_1.11.1     
[25] crayon_1.5.3       jquerylib_0.1.4    cachem_1.1.0       nlme_3.1-168      
[29] tidyselect_1.2.1   digest_0.6.39      stringi_1.8.7      labeling_0.4.3    
[33] splines_4.5.2      fastmap_1.2.0      grid_4.5.2         cli_3.6.5         
[37] magrittr_2.0.4     dichromat_2.0-0.1  withr_3.0.2        bit64_4.6.0-1     
[41] timechange_0.3.0   rmarkdown_2.30     httr_1.4.7         bit_4.6.0         
[45] otel_0.2.0         hms_1.1.4          evaluate_1.0.5     viridisLite_0.4.2 
[49] mgcv_1.9-3         rlang_1.1.6        glue_1.8.0         vroom_1.6.7       
[53] jsonlite_2.0.0     R6_2.6.1          

Rapport généré le 07 janvier 2026 à 05:48